#ifndef RENDERER_H
#define RENDERER_H

#pragma once
#include <sstream>
#include "Windows.h"
#include "DirectInput.h"
#include "Usefuls.h"
using namespace std;

class DirectInput;

const int	g_ciCubeVerts = 24;				// the number of vertices that make up a cube
const int	g_ciCubeIndices = 36;			// the number of indices that make up a cube
const int	g_ciPyrVerts = 16;				// number of vertices that make up a pyramid
const int	g_ciPyrIndices = 18;			// number of indices that make up a pyramid

class Renderer
{
private:
	Renderer();
	IDirect3D9*						m_pD3DObject;			// object used to create the device
	IDirect3DDevice9*				m_pD3DDevice;			// the main device
	CUSTOMVERTEX					m_cubeVerts[g_ciCubeVerts];		// array of vertices used to create the vertex buffer
	WORD							m_cubeIndices[g_ciCubeIndices];	// array of simple ints used to create the index buffer
	CUSTOMVERTEX					m_pyrVerts[g_ciPyrVerts];
	WORD							m_pyrIndices[g_ciPyrIndices];
	IDirect3DVertexBuffer9*			m_pCubeVertBuffer;		// the vertex buffer for cube
	IDirect3DIndexBuffer9*			m_pCubeIndexBuffer;		// the index buffer for cube
	IDirect3DVertexBuffer9*			m_pPyrVertBuffer;		// vertex buffer for the pyramid
	IDirect3DIndexBuffer9*			m_pPyrIndexBuffer;		// index buffer for the pyramid
	LPDIRECT3DVERTEXDECLARATION9	m_lpVertDecl;			// vertex declaration
	HWND							m_hWnd;					// a copy of hWnd from WinMain
	bool							m_bWindowed;
	float							m_fScreenWidth;
	float							m_fScreenHeight;
	d3dCamera						m_Camera;				// camera struct that holds the properties to make matView
	D3DXMATRIX						m_matView;				// the view of the camera
	D3DXMATRIX						m_matPerspective;		// perspective of the camera
	D3DLIGHT9						m_Light;
	D3DMATERIAL9					m_Materials[3];			// array of materials
	LPDIRECT3DTEXTURE9				m_lpTextures[3];		// array of textures
	ID3DXFont*						m_pD3DFont;				// used to display font
	ostringstream					m_oss;					// holds the display font
	RECT							m_FontBox;				// RECT holding the font

	D3DXMATRIX						m_matTransl;			// translation matrix
	D3DXMATRIX						m_matRot;				// rotation matrix
	D3DXMATRIX						m_matScale;				// scale matrix
	D3DXMATRIX						m_matWorld;


	// shader member variables
	ID3DXEffect*					m_pEffect;
	LPD3DXBUFFER*					m_pEffectError;
	D3DXHANDLE						m_hTech;
	UINT							m_passes;


	// shut up, I'm too lazy to make an object class for the object properties
	float	iCube1Angle;
	float	iCube2Angle;

	// pyramid variables
	float xPos, yPos, zPos;
	float xRot, yRot, zRot;
	float fScale;

	bool SetupDevice(HWND hWnd);
	bool SetupBuffers();
	bool SetupLight();
	bool SetupMatAndTex();
	bool SetupFont(int ScrWidth, int ScrHeight);
	void InitVertBuffers();								// called in init to fill the vertex buffer
	void InitIndexBuffers();							// called in init to fill the index buffer

public:

	static inline Renderer* Instance()
	{
		static Renderer theRenderer;
		return &theRenderer;
	}
	void Init(HWND hWnd);
	void Update();
	void RenderOneFrame();
	void Cleanup();
};

#endif